import * as jwt from 'jsonwebtoken';
import env from '../config/env';
const securityCode = env.token.securityCode;
const tokenOptions = {
    expiresIn: env.token.ttl
};

export class TokenService {
    public constructor(private secretOrPublicKey: string | Buffer, private signOptions?: jwt.SignOptions) {
        this.signOptions = {};
    }

    public sign(payload: string | Buffer | Object, signOptions?: jwt.SignOptions) {
        // exp is only set if the payload is an object literal
        Object.assign(this.signOptions, signOptions);
        if (!(payload instanceof Object)) delete this.signOptions.expiresIn;
        return jwt.sign(payload, this.secretOrPublicKey, this.signOptions);
    }

    public verifyToken(token: string, verifyOptions?: jwt.VerifyOptions): Promise<any> {
        return new Promise((resolve, reject) => jwt
            .verify(token, this.secretOrPublicKey, verifyOptions, (err, decoded) => {
                err ? resolve(0) : resolve(decoded);
            }));
    }

    public verifyHeader(headers, verifyOptions?: jwt.VerifyOptions): any {
        let { authorization } = headers;
        if (!authorization) return null;
        let token = this.getBearerToken(authorization);
        if (!token) return null;
        return this.verifyToken(token);
    }

    public getBearerToken(header: string): string {
        // 任意空白符重复0次或多次+字母或数字或下划线或汉字重复1次或多次+任意空白符重复1次或多次+任意非空白符重复1次或多次+任意空白符重复0次或多次、
        // 分割`Bearer xxxx.xxxx.xxxx`
        let groups = /^\s*(\w+)\s+(\S+)\s*$/.exec(header);
        if (!groups) return null;

        let schema = groups[1], token = groups[2];
        if (schema !== 'Bearer') return null;
        return token;
    }
}

export const tokenService = new TokenService(securityCode, tokenOptions);